﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Web;
using System.Data;
using System.Web.UI;
using System.Web.UI.WebControls;
using Telerik.Web.UI;
using _WebShared.Classes;
using KPIS.GERP.GHRMS.MODEL;
using KPIS.GERP.GHRMS.BLL;
using System.Security.AccessControl; 

namespace KPIS.GERP.GHRMS.APP.Classes
{
    public class Main
	{
        public int ConvertTimeToInt(TimeSpan? time) {
            string t = time == null ? "00:00:00" : time.ToString();
            string[] arrStr = t.Split(':');
            t = arrStr[0] + arrStr[1];
            return Convert.ToInt32(t);
        }

        public void ClearComboBox(ref RadComboBox radComboBox)
        {
            radComboBox.Text = null;
            radComboBox.SelectedValue = null;
            radComboBox.ClearSelection();
        }

		public Control FindControlRecursive(Control container, string name)
		{
			if (container.ID == name)
				return container;

			foreach (Control ctrl in container.Controls)
			{
				Control foundCtrl = FindControlRecursive(ctrl, name);
				if (foundCtrl != null)
					return foundCtrl;
			}
			return null;
		}

        public void ExpandParent(ref RadTreeNode selectedNode)
        {
            while(selectedNode.ParentNode != null)
            {
                selectedNode.ParentNode.ExpandChildNodes();
                selectedNode = selectedNode.ParentNode;
            }
        }

        public void FindRecursive(RadTreeNode treeNode, string strSearch)
        {
            foreach (RadTreeNode tn in treeNode.Nodes)
            {
                if (!String.IsNullOrEmpty(strSearch) && tn.Text.Contains(strSearch) )
                {
                    tn.BackColor = System.Drawing.Color.Yellow;
                    tn.ExpandParentNodes();
                }
                else
                    tn.BackColor = System.Drawing.Color.Transparent;
                FindRecursive(tn, strSearch);
            }
        }

        public void ClearRecursive(RadTreeNode treeNode, System.Drawing.Color color)
        {
            foreach (RadTreeNode tn in treeNode.Nodes)
            {
                tn.BackColor = color;
                ClearRecursive(tn, color);
            }
        }

        public int CalculateAge(DateTime dt)
        {
            int nYear = dt.Year;
            int nMonth = dt.Month;
            int nDay = dt.Day;
            int nYearNow = DateTime.Now.Year;
            int nMonthNow = DateTime.Now.Month;
            int nDayNow = DateTime.Now.Day;
            int nResult = 0;

            if (nDayNow - nDay < 0)
            {
                nDayNow = nDayNow + 30;
                if (nMonthNow - 1 > 0)
                {
                    nMonthNow = nMonthNow - 1;
                }
                else
                {
                    nMonthNow = 12;
                    nYearNow = nYearNow - 1;
                }
            }

            if (nMonthNow - nMonth < 0)
            {
                nMonthNow = nMonthNow + 12;
                nYearNow = nYearNow - 1;
            }

            nResult = Math.Abs(nYearNow - nYear);

            return nResult;
        }

        public int CalculateAgeMonth(DateTime dt)
        {
            int nYear = dt.Year;
            int nMonth = dt.Month;
            int nDay = dt.Day;
            int nYearNow = DateTime.Now.Year;
            int nMonthNow = DateTime.Now.Month;
            int nDayNow = DateTime.Now.Day;
            int nResult = 0;

            if (nDayNow - nDay < 0)
            {
                nDayNow = nDayNow + 30;
                if (nMonthNow - 1 > 0)
                {
                    nMonthNow = nMonthNow - 1;
                }
                else
                {
                    nMonthNow = 12;
                    nYearNow = nYearNow - 1;
                }
            }

            if (nMonthNow - nMonth < 0)
            {
                nMonthNow = nMonthNow + 12;
                nYearNow = nYearNow - 1;
            }

            nResult = Math.Abs(nMonthNow - nMonth);

            return nResult;
        }

        public int CalculateAgeDay(DateTime dt)
        {
            int nYear = dt.Year;
            int nMonth = dt.Month;
            int nDay = dt.Day;
            int nYearNow = DateTime.Now.Year;
            int nMonthNow = DateTime.Now.Month;
            int nDayNow = DateTime.Now.Day;
            int nResult = 0;

            if (nDayNow - nDay < 0)
            {
                nDayNow = nDayNow + 30;
                if (nMonthNow - 1 > 0)
                {
                    nMonthNow = nMonthNow - 1;
                }
                else
                {
                    nMonthNow = 12;
                    nYearNow = nYearNow - 1;
                }
            }

            if (nMonthNow - nMonth < 0)
            {
                nMonthNow = nMonthNow + 12;
                nYearNow = nYearNow - 1;
            }

            nResult = Math.Abs(nDayNow - nDay);

            return nResult;
        }

        public string ToDateOnly(string strDateTime)
        {
            if (DateTimeX.IsValidDmyDate(strDateTime, true))
            {
                string strDate = strDateTime.Substring(0, strDateTime.IndexOf(" "));
                return strDate;
            }
            else
            {
                return strDateTime;
            }
        }

        public string GetTrueFalseImage(string strCompare, string strTrue, string strFalse
            , string strTrueImageUrl, string strFalseImageUrl)
        {
            if (strCompare == strTrue)
                return strTrueImageUrl;
            else if (strCompare == strFalse)
                return strFalseImageUrl;
            else
                return null;
        }

        public void InsertEmptyDDLSelect(RadComboBox ddl)
        {
            RadComboBoxItem empty = new RadComboBoxItem("<เลือกรายการ>", "");
            ddl.Items.Insert(0, empty);
        }

        public void InsertEmptyDDLAll(RadComboBox ddl)
        {
            RadComboBoxItem empty = new RadComboBoxItem("<ทั้งหมด>", "");
            ddl.Items.Insert(0, empty);
        }

        public string ErrorEmpty(string strFieldName)
        {
            return "กรุณากรอกข้อมูล [" + strFieldName + "]";
        }

        public void MessageAlert(Page p, string strMessage)
        {
            strMessage = (strMessage ?? "").Replace("'", "").Replace("\"", "");
            ScriptManager.RegisterClientScriptBlock(p, p.GetType(), "onclick"
                , "window.alert('" + PreventErrorJScript(strMessage) + "');", true);
        }

		public void ReloadPage(Page p, string strMessage)
		{
			ScriptManager.RegisterClientScriptBlock(p, p.GetType(), "onclick"
                , "window.alert('" + PreventErrorJScript(strMessage) + "'); setTimeout('DelayToReloadAll()', 1000)", true);
		}

		public void ReloadCurrentPage(Page p, string strMessage)
		{
			ScriptManager.RegisterClientScriptBlock(p, p.GetType(), "onclick"
                , "window.alert('" + PreventErrorJScript(strMessage) + "'); setTimeout('DelayToReloadFrame()', 1000)", true);
		}
        
        public void MessageAlert2(Page p, Exception ex, string message = "")
        {
            message = PreventErrorJScript(message);
            var messageErrorAlert = "Error " + (!string.IsNullOrEmpty(message) ? message + "\n\n" : "");
            if(ex != null)
            {
                messageErrorAlert += "Exception : [" + ex.Message + "]\n\n";

                if(ex.InnerException != null)
                {
                    messageErrorAlert += ", Inner Exception : [" + ex.InnerException.Message + "]\n\n";

                    if(ex.InnerException.InnerException != null)
                    {
                        messageErrorAlert += ", Inner Exception 2nd : [" + ex.InnerException.InnerException.Message + "]\n\n";
                        
                        if(ex.InnerException.InnerException.InnerException != null)
                        {
                            messageErrorAlert += ", Inner Exception 3rd : [" + ex.InnerException.InnerException.InnerException.Message + "]\n\n";
                        }
                    }
                }
            }

            MessageAlert2(p, (messageErrorAlert??"").Replace("'","").Replace("\"", ""));

        }

        public void MessageAlert2(Page p, string strMessage)
        {
            RadAjaxManager.GetCurrent(p).Alert(PreventErrorJScript(strMessage));
        }

        public string PreventErrorJScript(string strMessage)
        {
            return (strMessage??"").Replace("'", "-").Replace("\"", "-").Replace("\r", "").Replace("\n", "").Replace("\\", "");
        }

        public string ConvertNumberToString(Object o)
        {
            string result = "";

            if (o == null)
            {
                result = "0.00";
            }
            else
            {
                switch (o.GetType().ToString())
                {
                    case "System.int":
                    case "System.Int32":
                        result = Convert.ToInt32(o).ToString("#,###.##");
                        break;
                    case "System.double":
                    case "System.Double":
                        result = Convert.ToDouble(o).ToString("#,###.##");
                        break;
                }
            }

            return result;
        }

        public int ConvertDefaultInt(Object o)
        {
            return ConvertNullInt(o)??new int();
        }

		public double ConvertDefaultDouble(Object o)
		{
			return ConvertNullDouble(o)??new double();
		}
        
		public decimal ConvertDefaultDecimal(Object o)
		{
			return ConvertNullDecimal(o)??new decimal();
		}
		public DateTime ConvertDefaultDateTime(Object o)
		{
			return ConvertNullDateTime(o)??new DateTime();
		}

        public Nullable<int> ConvertNullInt(Object o)
        {
            int tempInt;
            Nullable<int> result = (o == null ? null : (o.ToString().Length == 0 || !Int32.TryParse(o.ToString(), out tempInt) ? null : (Nullable<int>)tempInt));
            return result;
        }
        public Nullable<int> ConvertNullIntMakeZeroAsNull(Object o)
        {
            int tempInt;
            Nullable<int> result = (o == null ? null : (o.ToString().Length == 0 || !Int32.TryParse(o.ToString(), out tempInt) ? null : (Nullable<int>)tempInt));
            return result != 0 ? result : null;
        }

		public Nullable<double> ConvertNullDouble(Object o)
		{
			Nullable<double> result = (o == null ? null : (o.ToString().Length == 0 ? null : (Nullable<double>)Convert.ToDouble(o)));
			return result;
		}

		public Nullable<decimal> ConvertNullDecimal(Object o)
		{
			Nullable<decimal> result = (o == null ? null : (o.ToString().Length == 0 ? null : (Nullable<decimal>)Convert.ToDecimal(o)));
			return result;
		}

        public Nullable<DateTime> ConvertNullDateTime(Object o)
        {
            Nullable<DateTime> result = (o == null ? null : (o.ToString().Length == 0 ? null : (Nullable<DateTime>)Convert.ToDateTime(o)));
            return result;
        }

        public Nullable<TimeSpan> ConvertNullTimeSpan(Object o)
        {
            Nullable<TimeSpan> result = (o == null ? null : (o.ToString().Length == 0 ? null : (Nullable<TimeSpan>)Convert.ToDateTime(o).TimeOfDay));
            return result;
        }

        public object ConvertToDB(Object o)
        {
            return (o == null || o.ToString().Trim().Length == 0 ? DBNull.Value : o);
        }

        public string DateTimeNumber
        {
            get
            {
                var dt = DateTime.Now;
                CultureInfo ci = new CultureInfo("en-US");
                List<string> dtStr = new List<string>
                                         {
                                             dt.Year.ToString(ci),
                                             dt.Month.ToString(ci),
                                             dt.Day.ToString(ci),
                                             dt.Hour.ToString(ci),
                                             dt.Minute.ToString(ci),
                                             dt.Second.ToString(ci),
                                             dt.Millisecond.ToString(ci)
                                         };
                string result = "";
                const string seperator = "";
                foreach (string s in dtStr)
                {
                    result += s + seperator;
                }
                if (result.Length > 0) 
                    result = result.Substring(0, result.Length - seperator.Length - 1);

                return result;
            }
        }

        public string WebString(string strValue)
        {
            string strResult = strValue.Replace("&nbsp;", "").Replace("\r\n", "<br />");

            return strResult;
        }

        public static void ExportExcel(DataSet ds, string fileName = "Result.xls")
        {
            HttpResponse response = HttpContext.Current.Response;
            // first let's clean up the response.object
            response.Clear();
            response.Charset = "UTF-8"; 
            response.ContentEncoding = System.Text.Encoding.UTF8; 

            // set the response mime type for excel
            response.ContentType = "application/vnd.ms-excel";
            response.AddHeader("Content-Disposition",
                               string.Format("attachment;filename=\"{0}\"", fileName));

            using (StringWriter sw = new StringWriter())
            {
                using (HtmlTextWriter htw = new HtmlTextWriter(sw))
                {
                    // instantiate a datagrid
                    DataGrid dg = new DataGrid();
                    dg.DataSource = ds.Tables[0];
                    dg.DataBind();
                    dg.RenderControl(htw);
                    response.Write(sw.ToString());
                    dg.Dispose();
                    ds.Dispose();
                    response.End();
                }
            }
        }

        public string strYearTh2En(string year)
        {
            if (!String.IsNullOrEmpty(year))
            {
                if (Convert.ToInt32(year) > 2550)
                    year = (Convert.ToInt32(year) - 543).ToString();
            }

            return year;
        }

        public int? ConvertDecimalToInt(decimal? d)
        {
            int? result;
            d = d != null ? Math.Ceiling(d.Value) : 0;
            result = Convert.ToInt32(d);
            result = result == 0 ? null : result;
            return result;
        }

        public void FolderACL(String accountName, String folderPath)
        {
            FileSystemRights Rights;

            //What rights are we setting?
            Rights = FileSystemRights.FullControl;
            bool modified;
            InheritanceFlags none = new InheritanceFlags();
            none = InheritanceFlags.None;

            //set on dir itself
            FileSystemAccessRule accessRule = new FileSystemAccessRule(accountName, Rights, none, PropagationFlags.NoPropagateInherit, AccessControlType.Allow);
            DirectoryInfo dInfo = new DirectoryInfo(folderPath);
            DirectorySecurity dSecurity = dInfo.GetAccessControl();
            dSecurity.ModifyAccessRule(AccessControlModification.Set, accessRule, out modified);

            //Always allow objects to inherit on a directory 
            InheritanceFlags iFlags = new InheritanceFlags();
            iFlags = InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit;

            //Add Access rule for the inheritance
            FileSystemAccessRule accessRule2 = new FileSystemAccessRule(accountName, Rights, iFlags, PropagationFlags.InheritOnly, AccessControlType.Allow);
            dSecurity.ModifyAccessRule(AccessControlModification.Add, accessRule2, out modified);

            dInfo.SetAccessControl(dSecurity);
        }

        private bool IsAValidNumber(string strNumberText)
        {
            // There can be only one point and the others must be 0-9
            int i;
            int nPointCount = 0;
            string strChar;
            bool bOK = true;

            for (i = 0; i < strNumberText.Length; i++)
            {
                strChar = strNumberText.Substring(i, 1);

                if (strChar == ".")
                    nPointCount++;

                if (nPointCount > 1 || strChar != "." && (int.Parse(strChar) < 0 || int.Parse(strChar) > 9))
                {
                    bOK = false;
                    break;
                }
            }

            return bOK;
        }

        private string EachNumberPositionThaiText(string strReverseNumberText, int nMaxPosition
            , int nCurrentPosition, string[] astrPositionName, string[] astrDigitName)
        {
            int nDigit;
            string strDigitName;
            int nPosition;
            string strPositionName;
            int nPreviousDigit = 0;

            nDigit = int.Parse(strReverseNumberText.Substring(nCurrentPosition, 1));

            if (nCurrentPosition < nMaxPosition)
                nPreviousDigit = int.Parse(strReverseNumberText.Substring(nCurrentPosition + 1, 1));
            // notice: lngPosition = (lngCurrentPosition - 1) Mod 6 + 1
            nPosition = (nCurrentPosition - 1) % 6 + 1;

            if (nDigit == 0 && nMaxPosition > 0 || nDigit == 1 && nPosition == 1)
                strDigitName = "";
            else if (nDigit == 1 && (nPosition == 0 || nPosition == 6)
                && nMaxPosition > nCurrentPosition
                && nPreviousDigit > 0)
                strDigitName = "เอ็ด";
            else if (nDigit == 2 && nPosition == 1)
                strDigitName = "ยี่";
            else
                strDigitName = astrDigitName[nDigit];

            if (nDigit == 0 && nPosition != 6)
                strPositionName = "";
            else
                strPositionName = astrPositionName[nPosition];

            return strDigitName + strPositionName;
        }

        public string MoneyTextThai(double dblNumber)
        {
            return MoneyTextThai(dblNumber.ToString(), "บาท", "สตางค์");
        }

        public string MoneyTextThai(decimal dblNumber)
        {
            return MoneyTextThai(dblNumber.ToString(), "บาท", "สตางค์");
        }

        public string MoneyTextThai(string strNumberText)
        {
            return MoneyTextThai(strNumberText, "บาท", "สตางค์");
        }

        public string MoneyTextThai(string strNumberText, string strCurrencyMain, string strCurrencyPercent)
        {
            string strResult = "";
            string[] astrPositionName = { "", "สิบ", "ร้อย", "พัน", "หมื่น", "แสน", "ล้าน" };
            string[] astrDigitName = { "ศูนย์", "หนึ่ง", "สอง", "สาม", "สี่", "ห้า", "หก", "เจ็ด", "แปด", "เก้า" };
            string strReverseBaht;
            string strReverseSatang;
            int nPointPosition;
            int nMaxPosition;
            int nCurrentPosition;

            // simplify the number
            strNumberText = strNumberText.Trim().Replace(",", "");

            while (strNumberText.Length > 1
                && StringX.Left(strNumberText, 1) == "0"
                && StringX.Left(strNumberText, 2) != "0.")
                strNumberText = strNumberText.Substring(1);

            // check number validation
            if (!IsAValidNumber(strNumberText))
                throw new Exception(strNumberText + " ไม่ใช่จำนวนที่ถูกต้อง");

            // separate baht and satang
            nPointPosition = strNumberText.IndexOf(".");

            if (nPointPosition >= 0)
            {
                strReverseBaht = StringX.StrReverse(strNumberText.Substring(0, nPointPosition));
                strReverseSatang
                    = StringX.StrReverse(StringX.Right(double.Parse(strNumberText.Substring(nPointPosition)).ToString(".00"), 2));
            }
            else
            {
                strReverseBaht = StringX.StrReverse(strNumberText);
                strReverseSatang = "00";
            }

            // begin process baht
            nMaxPosition = strReverseBaht.Length - 1;

            for (nCurrentPosition = nMaxPosition; nCurrentPosition >= 0; nCurrentPosition--)
            {
                strResult += EachNumberPositionThaiText(strReverseBaht
                    , nMaxPosition, nCurrentPosition, astrPositionName, astrDigitName);
            }

            if (strResult.Length > 0)
                strResult += strCurrencyMain;
            // end process baht

            // begin process satang
            if (strResult.Length > 0 && strReverseSatang == "00")
            {
                strResult += "ถ้วน";
            }
            else
            {
                if (strResult == "ศูนย์ " + strCurrencyMain)
                    strResult = "";

                nMaxPosition = strReverseSatang.Length - 1;

                for (nCurrentPosition = nMaxPosition; nCurrentPosition >= 0; nCurrentPosition--)
                    strResult += EachNumberPositionThaiText(strReverseSatang
                        , nMaxPosition, nCurrentPosition, astrPositionName, astrDigitName);

                if (strResult.Length > 0)
                    strResult += strCurrencyPercent;
            }
            // end process satang

            return strResult;
        }

        #region[Check Weekend & Holiday]
        public int GetRegularWorkingDays(DateTime start, DateTime end)
        {
            // ตรวจสอบ เสาร์ อาทิตย์ และวันหยุด .Where(x => CheckHoliday(x.ToShortDateString()) == 0)//
            return Range(start, end)
                .Where(x => x.DayOfWeek != DayOfWeek.Sunday)
                .Where(x => x.DayOfWeek != DayOfWeek.Saturday)
                .Where(x => CheckHoliday(x.ToShortDateString()) == 0)
                .Count();
        }

        public int GetRegularAllDays(DateTime start, DateTime end)
        {
            return (
                from day in Range(start, end)
                select day).Count();
        }

        static IList<NonWorkingDayInfo> non_wd_lst;
        private int CheckHoliday(string d)
        {
            if (non_wd_lst == null)
            {
                non_wd_lst = new NonWorkingDayBLL().GetAllNonWorkingDays(
                    (new ThaiBuddhistCalendar().GetYear(DateTime.Now)).ToString());
            }
            //d en-Us
            var c = from item in non_wd_lst
                    where item.Date.Value.ToShortDateString().Equals(d)
                    select non_wd_lst;
            return c.ToList().Count();
        }

        IEnumerable<DateTime> Range(DateTime start, DateTime end)
        {
            while (start <= end)
            {
                yield return start;
                start = start.AddDays(1);
            }
        }

        public int GetWorkingDaysByMonth(string month, string year)
        {
            int ret = 0;
            DateTime firstDayOfTheMonth = new DateTime(Convert.ToInt32(year), Convert.ToInt32(month), 1);
            var first = DateTime.Now.ToString("yyyy-MM-dd", new System.Globalization.CultureInfo("en-US"));
            DateTime LastDayOfTheMonth = firstDayOfTheMonth.AddMonths(1).AddDays(-1);

            ret = GetRegularWorkingDays(firstDayOfTheMonth, LastDayOfTheMonth);

            return ret;
        }

        #endregion[Check Weekend & Holiday]

        #region Properties

        public enum EditMode
        {
            AddNew
            , Edit
            , View
            , Info
            , ShowGrid
        }
        #endregion

        public void WriteLogToDatabase(string message)
        {
            KPIS.DBM.DBManager dbManager = new KPIS.DBM.DBManager(SystemInfo._DataProvider, SystemInfo._ConnectionString);
              
            try{
                dbManager.Open();
                dbManager.CreateParameters(1);
                dbManager.AddParameters(0, "@message", message);

                string strSQL = @"IF  NOT EXISTS (SELECT * FROM sys.objects 
                                    WHERE object_id = OBJECT_ID(N'[dbo].[SysLog]') AND type in (N'U'))

                                    BEGIN

                                    CREATE TABLE SysLog (
                                                            Id [int] IDENTITY(1,1) NOT NULL,
                                                            CreateWhen datetime2,
                                                            Message text,
						                                    PRIMARY KEY (Id)
                                                        );

                                    END
                                     ";
                dbManager.ExecuteNonQuery(CommandType.Text, strSQL);            
                strSQL = @"INSERT INTO [dbo].[SysLog] ([CreateWhen], [Message]) VALUES ( GETDATE(), @message)";
                dbManager.ExecuteNonQuery(CommandType.Text, strSQL);             
            }
            catch (Exception ex)
            {
                throw (ex);
            }
            finally
            {
                dbManager.CloseReader();
                dbManager.Dispose();
            }
        }
    }
}
